package com.neusoft.aclome.cmp.cloud.server.jcce.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.neusoft.aclome.cmp.cloud.api.request.vm.VmRequest;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.Overview2DTO;
import com.neusoft.aclome.cmp.cloud.server.jcce.entity.Kt2ConsultProcessData;
import com.neusoft.aclome.cmp.cloud.server.jcce.repository.Kt2ConsultProcessDataMapper;
import com.neusoft.aclome.cmp.cloud.server.model.entity.DataCenterEntity;
import com.neusoft.aclome.cmp.cloud.server.model.entity.VirtualMachineEntity;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.config.DriverFactory;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.entity.CloudPlatformEntity;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.service.CloudPlatformService;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.service.PubRdsMysqlInstanceService;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.service.PubVirtualMachineService;
import com.neusoft.aclome.cmp.cloud.server.service.DataCenterService;
import com.neusoft.aclome.cmp.cloud.server.service.OrganizationService;
import com.neusoft.aclome.cmp.cloud.server.service.VirtualMachineService;
import com.neusoft.aclome.cmp.common.constants.AclomeCmpOrganizationType;
import com.neusoft.aclome.cmp.common.constants.CloudProviderType;
import com.neusoft.aclome.cmp.common.model.vo.HttpResponse;
import com.neusoft.aclome.cmp.common.model.vo.ResponsePage;
import com.neusoft.aclome.cmp.organization.api.model.vo.ResourcePoolVO;
import com.neusoft.pub.cloud.provider.driver.*;
import com.neusoft.pub.cloud.provider.entity.*;
import com.neusoft.pub.cloud.provider.enums.CloudProviderCode;
import com.neusoft.pub.cloud.provider.request.*;
import io.swagger.models.auth.In;
import org.apache.commons.collections.list.AbstractListDecorator;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class JcceKT1Service {

    private static final Logger log = LoggerFactory.getLogger(JcceKT1Service.class);

    @Autowired
    private DataCenterService dataCenterService;

    @Autowired
    private CloudPlatformService cloudPlatformService;

    @Autowired
    private PubVirtualMachineService pubVirtualMachineService;

    @Autowired
    private VirtualMachineService privateVirtualMachineService;

    @Autowired
    private PubRdsMysqlInstanceService pubRdsMysqlInstanceService;

    @Autowired
    private DriverFactory driverFactory;

    @Autowired
    private Kt2ConsultProcessDataMapper kt2ConsultProcessDataMapper;

    @Value("${jcce-url.kt1.consultationProcess}")
    private String consultationProcessUrl;

    @Autowired
    private OrganizationService organizationService;

    private RestTemplate restTemplate = new RestTemplate();

    public HttpResponse overview() {
        JSONArray result = new JSONArray();

        CloudPlatformRequest req = new CloudPlatformRequest();
        req.setPageNo(1);
        req.setPageSize(1000);

        // 云商信息
        ResponsePage<CloudPlatformEntity> cloudPlatformEntity = cloudPlatformService.getCloudPlatformList(req);

        for (CloudPlatformEntity cloud : cloudPlatformEntity.getPageData()) {
            cloud.setSecretKey("");

            AuthInfo authInfo = driverFactory.getAuthInfoByDataCenterId(cloud.getId());
            Secret.putValue(authInfo);

            JSONObject obj = new JSONObject();
            obj.put("id", cloud.getId());
            obj.put("name", cloud.getPlatformName());

            // 实例信息
            ListVirtualMachineRequest req1 = new ListVirtualMachineRequest();
            req1.setDataCenterId(cloud.getId());
            ResponsePage<VirtualMachine> vms = pubVirtualMachineService.listLocalInstance(req1);

            obj.put("vmTotal", vms.getTotal());
//            obj.put("vmQuota", cloud.getVmQuota());

            // 网络
            VpcDriver vpcDriver = driverFactory.getDriver(VpcDriver.class);
            BaseRequest request = new BaseRequest();
            request.setRegionId(cloud.getRegionId());
            Page<Vpc> vpcs = vpcDriver.getVpcList(request);
            obj.put("vpcTotal", vpcs.getTotal());
//            obj.put("vpcQuota", cloud.getVpcQuota());

            // 数据库
            ListRdsLocalInstanceRequest req2 = new ListRdsLocalInstanceRequest();
            req2.setDataCenterId(cloud.getId());
            ResponsePage<PubRdsInstance> rdsList = pubRdsMysqlInstanceService.listLocalInstance(req2);

            obj.put("rdsTotal", rdsList.getTotal());
//            obj.put("rdsQuota", cloud.getRdsQuota());

            // TODO 磁盘
            VolumeDriver volumeDriver = driverFactory.getDriver(VolumeDriver.class);
            List<Volume> volumes = volumeDriver.getVolumeList(request).getPageData();
            obj.put("volumnTotal", volumes.size());
//            obj.put("volumnQuota", cloud.getDiskNumQuota());
            obj.put("volumnCapacity", volumes.stream().mapToInt(v -> v.getDiskSize()).sum());
//            obj.put("volumnCapacityQuota", cloud.getDiskCapacityQuota());

            // TODO 中间件
            obj.put("middlewareTotal", 0);
            obj.put("middlewareQuota", 0);

            result.add(obj);
        }
        return HttpResponse.resultSuccess(result);
    }

    public HttpResponse vms(Integer dataCenterId) {
        JSONObject result = new JSONObject();

        // 云商信息
        CloudPlatformEntity cloud = cloudPlatformService.getById(Long.valueOf(dataCenterId));

        // 实例信息
        ListVirtualMachineRequest req1 = new ListVirtualMachineRequest();
        req1.setDataCenterId(cloud.getId());
        ResponsePage<VirtualMachine> vms = pubVirtualMachineService.listLocalInstance(req1);

        Map<String, InstanceType> instanceTypeMap = getInstanceTypeMap(cloud);
        Map<String, Integer> typeTotalMap = new HashMap();

        vms.getPageData().forEach(vm -> {
            InstanceType type = instanceTypeMap.get(vm.getInstanceType());
            if (type != null) {
                if (typeTotalMap.get(type.getInstanceType()) == null) {
                    typeTotalMap.put(type.getInstanceType(), 1);
                } else {
                    Integer i = typeTotalMap.get(type.getInstanceType());
                    typeTotalMap.put(type.getInstanceType(), (i + 1));
                }
            }

        });

        JSONArray types = new JSONArray();

        instanceTypeMap.keySet().forEach(key -> {
            if (typeTotalMap.get(key) != null) {
                InstanceType t = instanceTypeMap.get(key);
                JSONObject json = (JSONObject) JSONObject.toJSON(t);
                json.put("vmTotal", typeTotalMap.get(key));
                types.add(json);
            }
        });

        result.put("type", types);
        return HttpResponse.resultSuccess(result);
    }

    public HttpResponse volumns(Integer dataCenterId) {
        AuthInfo authInfo = driverFactory.getAuthInfoByDataCenterId(dataCenterId);
        Secret.putValue(authInfo);

        JSONObject result = new JSONObject();

        // 云商信息
        CloudPlatformEntity cloud = cloudPlatformService.getById(Long.valueOf(dataCenterId));
        VolumeDriver driver1 = driverFactory.getDriver(VolumeDriver.class);

        DiskTypeRequest request = new DiskTypeRequest();
        request.setRegionId(cloud.getRegionId());

        // 云盘列表
        List<Volume> volumes = driver1.getVolumeList(request).getPageData();

        // 类型列表
        Map<String, Disk> typeMap = getDiskTypeMap(cloud);

        Map<String, Integer> typeTotalMap = new HashMap();
        Map<String, Integer> typeSizeMap = new HashMap();

        // 云盘，累加数量和容量
        volumes.forEach(vol -> {
            Disk disk = typeMap.get(vol.getDiskType());
            if (disk != null) {
                if (typeTotalMap.get(vol.getDiskType()) == null) {
                    typeTotalMap.put(vol.getDiskType(), 1);
                } else {
                    Integer i = typeTotalMap.get(vol.getDiskType());
                    typeTotalMap.put(vol.getDiskType(), (i + 1));
                }
                if (typeSizeMap.get(vol.getDiskType()) == null) {
                    typeSizeMap.put(vol.getDiskType(), vol.getDiskSize());
                } else {
                    Integer i = typeSizeMap.get(vol.getDiskType());
                    typeSizeMap.put(vol.getDiskType(), (i + vol.getDiskSize()));
                }
            }
        });

        JSONArray types = new JSONArray();

        typeMap.keySet().forEach(key -> {
            if (typeTotalMap.get(key) != null) {
                Disk disk = typeMap.get(key);
                JSONObject json = new JSONObject();
                json.put("diskName", disk.getDiskName());
                json.put("diskType", disk.getDiskType());
                // JSONObject json = (JSONObject) JSONObject.toJSON(disk);
                json.put("diskTotal", typeTotalMap.get(key));
                json.put("diskSize", typeSizeMap.get(key));
                types.add(json);
            }
        });

        result.put("type", types);
        return HttpResponse.resultSuccess(result);
    }


    public HttpResponse rds(Integer dataCenterId) {
        ListRdsLocalInstanceRequest req = new ListRdsLocalInstanceRequest();
        req.setDataCenterId(dataCenterId);
        List<PubRdsInstance> list = pubRdsMysqlInstanceService.listLocalInstance(req).getPageData();
        return HttpResponse.resultSuccess(list);
    }

    private Map<String, Disk> getDiskTypeMap(CloudPlatformEntity cloud) {
        DiskTypeRequest request = new DiskTypeRequest();
        request.setRegionId(cloud.getRegionId());

        DiskTypeDriver driver2 = driverFactory.getDriver(DiskTypeDriver.class);

        List<Disk> list = driver2.list(request);
        Map<String, Disk> diskTypeMap = new HashMap<>();

        list.forEach(d -> {
            diskTypeMap.put(d.getDiskType(), d);
        });

        return diskTypeMap;
    }

    private Map<String, InstanceType> getInstanceTypeMap(CloudPlatformEntity cloud) {
        Map<String, InstanceType> instanceTypeMap = new HashMap<>();
        Map<String, InstanceFamily> instanceFamilyMap = new HashMap<>();

        AuthInfo authInfo = driverFactory.getAuthInfoByDataCenterId(cloud.getId());
        Secret.putValue(authInfo);

        // 实例规格
        InstanceTypeRequest req2 = new InstanceTypeRequest();
        req2.setRegionId(cloud.getRegionId());
        req2.setPageNumber(1);
        req2.setPageSize(10000);

        InstanceTypeDriver instanceTypeDriver = driverFactory.getDriver(InstanceTypeDriver.class);
        Page<InstanceType> types = instanceTypeDriver.listInstanceType(req2);
        List<InstanceFamily> familyies = instanceTypeDriver.listInstanceFamily(req2);

        familyies.forEach(family -> {
            instanceFamilyMap.put(family.getInstanceFamily(), family);
        });

        types.getPageData().forEach(type -> {
            if (!StringUtils.isEmpty(type.getInstanceTypeFamily())) {
                InstanceFamily f = instanceFamilyMap.get(type.getInstanceTypeFamily());
                if (f != null) {
                    type.setInstanceTypeFamilyName(f.getInstanceFamilyName());
                }
            }
            instanceTypeMap.put(type.getInstanceType(), type);
        });

        return instanceTypeMap;
    }

    public JSONArray getConsultationProcess(){
        JSONArray resultArray = new JSONArray();
        List<Kt2ConsultProcessData> list = kt2ConsultProcessDataMapper.selectData();
        if (CollectionUtils.isNotEmpty(list)){
            resultArray = list.get(0).getInfo();
        }else {
            //访问外部接口
            String resp = restTemplate.getForObject(consultationProcessUrl, String.class, new HashMap<>());
            resultArray = JSONArray.parseArray(resp);
        }
        return resultArray;
    }

    // 新版磋商概览页面
    public HttpResponse overview2() {
        List<Overview2DTO> result = new ArrayList<>();

        // 公私有云云商列表
        List<CloudPlatformEntity> publicList = cloudPlatformService.getCloudPlatformList(new CloudPlatformRequest()).getPageData();
        List<DataCenterEntity> privateList = dataCenterService.listDataCenter(false, false, false);

        // 公私有云虚拟机
        ListVirtualMachineRequest pubReq = new ListVirtualMachineRequest();
        pubReq.setPageNumber(1);
        pubReq.setPageSize(1000);
        List<VirtualMachine> pubVMs = pubVirtualMachineService.listLocalInstance(pubReq).getPageData();

        // 私有云虚拟机
        List<VirtualMachineEntity> privateVMs = new ArrayList<>();
        Map<Integer, ResourcePoolVO> privateIdMap = new HashMap<>();
        try {
            privateVMs = privateVirtualMachineService.listVMs(new VmRequest());

            // 私有云配额，以云商ID为key
            privateIdMap = organizationService.listResourcePoolByType(AclomeCmpOrganizationType.DATA_CENTER)
                    .getData().stream().collect(Collectors.toMap(x -> x.getDataCenterId(), Function.identity(), (u, v) -> v, HashMap::new));
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 循环每个公有云商类型, 暂时排除联通
        for (CloudProviderCode code : CloudProviderCode.values()) {
            if (!CloudProviderCode.WOCLOUD.equals(code)) {
                Overview2DTO dto = findByCloudProviderCode(publicList, code, pubVMs);
                result.add(dto);
            }
        }

        // 循环每个私有云商类型
        List<CloudProviderType> privateTypes = new ArrayList<>();
        privateTypes.add(CloudProviderType.VMware);
        // privateTypes.add(CloudProviderType.Nutanix);
        for (CloudProviderType code : privateTypes) {
            Overview2DTO dto = findByPrivateProviderCode(privateList, code, privateVMs, privateIdMap);
            result.add(dto);
        }

        return HttpResponse.resultSuccess(result);
    }

    private Overview2DTO findByPrivateProviderCode(List<DataCenterEntity> list, CloudProviderType type, List<VirtualMachineEntity> vms, Map<Integer, ResourcePoolVO> privateIdMap) {
        Overview2DTO dto = new Overview2DTO(null, getCloudTypeName(type), "私有云");
        List<Overview2DTO.CloudTypeInit> typeInits = new ArrayList<>();
        List<Overview2DTO.CloudTypeProp> props = new ArrayList<>();

        List<DataCenterEntity> resList = list.stream().filter(e -> type.equals(e.getDataCenterContextEntity().getCloudProviderType())).collect(Collectors.toList());
        List<Integer> dataCenterIds = resList.stream().map(DataCenterEntity::getId).collect(Collectors.toList());

        // 云商名称
        resList.forEach(c -> typeInits.add(new Overview2DTO.CloudTypeInit(c.getId(), c.getName())));

        long cpuTotal = privateIdMap.keySet().stream().filter(dataCenterIds::contains).mapToLong(k -> privateIdMap.get(k).getVcpus()).sum();
        long memTotal = privateIdMap.keySet().stream().filter(dataCenterIds::contains).mapToLong(k -> privateIdMap.get(k).getMem() / 1024 / 1024 / 1024).sum();
        long storageTotal = privateIdMap.keySet().stream().filter(dataCenterIds::contains).mapToLong(k -> privateIdMap.get(k).getStorage() / 1024 / 1024 / 1024).sum();

        // 过滤出本云商的虚拟机
        List<VirtualMachineEntity> vmList = vms.stream().filter(vm -> dataCenterIds.contains(vm.getResourceDataCenterId())).collect(Collectors.toList());

        long cpuValue = vmList.stream().mapToLong(vm -> vm.getCpu()).sum();
        long memValue = vmList.stream().mapToLong(vm -> vm.getMemory()).sum() / 1024 / 1024 / 1024;
        long storageValue = vmList.stream().mapToLong(vm -> vm.getDisk()).sum() / 1024 / 1024 / 1024;
        return getOverview2DTO(dto, typeInits, props, cpuTotal, memTotal, storageTotal, cpuValue, memValue, storageValue);
    }

    private Overview2DTO findByCloudProviderCode(List<CloudPlatformEntity> list, CloudProviderCode code, List<VirtualMachine> vms) {
        Overview2DTO dto = new Overview2DTO(null, getCloudTypeName(code), "公有云");
        List<Overview2DTO.CloudTypeInit> typeInits = new ArrayList<>();
        List<Overview2DTO.CloudTypeProp> props = new ArrayList<>();
        List<CloudPlatformEntity> resList = list.stream().filter(e -> code.toString().equals(e.getCloudProvider())).collect(Collectors.toList());

        // 云商名称
        resList.forEach(c -> typeInits.add(new Overview2DTO.CloudTypeInit(c.getId(), c.getPlatformName())));

        long cpuTotal = resList.stream().mapToLong(r -> r.getCpuQuota() != null ? r.getCpuQuota() : 0).sum();
        long memTotal = resList.stream().mapToLong(r -> r.getMemQuota() != null ? r.getMemQuota() : 0).sum();
        long storageTotal = resList.stream().mapToLong(r -> r.getCapacityQuota() != null ? r.getCapacityQuota() : 0).sum();

        // 过滤出本云商的虚拟机
        List<VirtualMachine> vmList = vms.stream().filter(vm -> resList.stream().map(r -> r.getId()).collect(Collectors.toList()).contains(vm.getDataCenterId())).collect(Collectors.toList());

        // 通过虚拟机查已用配额
        long cpuValue = vmList.stream().mapToLong(vm -> vm.getCpu()).sum();
        long memValue = vmList.stream().mapToLong(vm -> vm.getMemory()).sum() / 1024;
        // TODO 目前虚拟机表没保存存储 暂时替代
        Integer storageValue = new Double(((double) cpuValue / (double) cpuTotal) * storageTotal).intValue();
        return getOverview2DTO(dto, typeInits, props, cpuTotal, memTotal, storageTotal, cpuValue, memValue, storageValue);
    }

    private Overview2DTO getOverview2DTO(Overview2DTO dto, List<Overview2DTO.CloudTypeInit> typeInits, List<Overview2DTO.CloudTypeProp> props, long cpuTotal, long memTotal, long storageTotal, long cpuValue, long memValue, long storageValue) {
        props.add(new Overview2DTO.CloudTypeProp("cpu", "CPU数量", cpuValue, cpuTotal));
        props.add(new Overview2DTO.CloudTypeProp("memory", "内存量", memValue, memTotal));
        props.add(new Overview2DTO.CloudTypeProp("storage", "存储量", storageValue, storageTotal));
        dto.setProps(props);
        dto.setInitList(typeInits);
        return dto;
    }

    private String getCloudTypeName(CloudProviderCode code) {
        if (CloudProviderCode.ALIYUN.equals(code)) {
            return "阿里云";
        }
        if (CloudProviderCode.HUAWEI.equals(code)) {
            return "华为云";
        }
        if (CloudProviderCode.BAIDU.equals(code)) {
            return "百度云";
        }
        if (CloudProviderCode.VOLCENGINE.equals(code)) {
            return "火山云";
        }
        // if (CloudProviderCode.WOCLOUD.equals(code)) {
        //     return "联通云";
        // }
        if (CloudProviderCode.TENCENT.equals(code)) {
            return "腾讯云";
        }
        return "";
    }

    private String getCloudTypeName(CloudProviderType type) {
        if (CloudProviderType.VMware.equals(type)) {
            return "威睿VMware";
        }
        if (CloudProviderType.Nutanix.equals(type)) {
            return "路坦力Nutanix";
        }
        return "";
    }
}
